package com.example.scrambledpuzzle;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.media.MediaPlayer;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.ImageColumns;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import android.widget.ImageView;

public class PuzzleLogic {

	/// Tag for logging
	private static final String TAG = "PuzzleActivity";
	//boolean fromGallery=false;
	ContentResolver cr;
	int match=0;
	private MediaPlayer mp = null;
	private Context mContext;
	// number of pieces to split
	private static final int NUM_OF_PIECES = 9;
	Bitmap mScratch;
	// bitmap array pieces
	Bitmap[] mBmpPieces;
	// list to keep track of image pieces in the gallery
	List<Integer> mGalleryList=new ArrayList<Integer>();



	///This constructor initializes the context of the application.
	public PuzzleLogic(Context con){
		mContext=con;
	}

	///This method creates a bitmap from the path/id, resizes it and then creates pieces.
	public boolean initializePuzzleLogic(int resId,String cameraPath, Uri galleryUriPath,boolean fromGallery){


		if(!fromGallery){
			if (cameraPath != null){
				//mScratch=BitmapFactory.decodeFile(cameraPath);
				decodeSampledBitmapFromResources(null, 0,cameraPath);
				fromGallery=true;

			}else if(galleryUriPath !=null){

				mScratch = getBitmap(galleryUriPath);
				fromGallery=true;

			}
			else if(resId != 0){
				//scratch=decodeSampledBitmapFromResource(getResou`1rces(), resId,620,440);

				//mScratch=BitmapFactory.decodeResource(mContext.getResources(),resId);
			decodeSampledBitmapFromResources(mContext.getResources(),resId,null);
				//Log.v(TAG,"Length of bitmap pieces"  + mBmpPieces.length);
				

				fromGallery=false;
			}
		}else{
			generateImage();
			fromGallery=true;
		}

		if(mScratch !=null){
			resizeBitmap();
			
			createBitmapPieces();
			//Log.v(TAG,"mgalleryList = " + mGalleryList.get(0));
		}
		return fromGallery;

	}

	private  Bitmap decodeSampledBitmapFromResources(Resources res, int resId,String cameraPath) {
		// First decode with inJustDecodeBounds=true to check dimensions
	    final BitmapFactory.Options options = new BitmapFactory.Options();
	   
	    options.inJustDecodeBounds = true;
	    if (resId!= 0){
	    BitmapFactory.decodeResource(res, resId, options);
	    }else if(cameraPath !=null){
	    	BitmapFactory.decodeFile(cameraPath,options);
	    }
	    
	    
	 // Calculate inSampleSize
	    options.inSampleSize = calculateInSampleSize(options);
	    Log.v(TAG,"sample size = " + options.inSampleSize);
	 // Decode bitmap with inSampleSize set
	    options.inJustDecodeBounds = false;
	    if(resId !=0){
	    mScratch= BitmapFactory.decodeResource(res, resId, options);
	    } else if (cameraPath !=null){
	    	mScratch= BitmapFactory.decodeFile(cameraPath, options);
	    }
		return mScratch;
		
	}

	private int calculateInSampleSize(BitmapFactory.Options options) {
		
		// Raw height and width of image
	    final int height = options.outHeight;
	    final int width = options.outWidth;
	    float aspectRatio = (float) width / (float) height;
	    //Display display = ((WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE)).getDefaultDisplay();
		//int reqWidth = display.getWidth();
	    int reqWidth=pixelsFromDp(500);
		int reqHeight=(int) (reqWidth/aspectRatio);
		
		//int reqHeight = (int) (reqWidth / aspectRatio);
	    
	    //int reqHeight=(int) (reqWidth/aspectRatio);
	    int inSampleSize = 1;

	    if (height > reqHeight || width > reqWidth) {

	        // Calculate ratios of height and width to requested height and width
	        final int heightRatio = Math.round((float) height / (float) reqHeight);
	        final int widthRatio = Math.round((float) width / (float) reqWidth);

	        // Choose the smallest ratio as inSampleSize value, this will guarantee
	        // a final image with both dimensions larger than or equal to the
	        // requested height and width.
	        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
	    }

	    return inSampleSize;
	}

	private int pixelsFromDp(int pixels) {
		return (int) (pixels * mContext.getResources().getDisplayMetrics().density + 0.5f);
	}

	///This method removes the old reference from mGalleryList and adds the new dropped 
	//cell's index during the drag and drop of image.It helps in swapping the image.
	public void dropHandler(int dropLocationIndex,int imageindex){

		if ((imageindex >= 0) && (imageindex < NUM_OF_PIECES)){
			int droppedGalleryIndex=mGalleryList.indexOf(dropLocationIndex);
			int draggedGalleryIndex=mGalleryList.indexOf(imageindex);
			mGalleryList.remove(droppedGalleryIndex);
			mGalleryList.add(droppedGalleryIndex, imageindex);

			mGalleryList.remove(draggedGalleryIndex);
			mGalleryList.add(draggedGalleryIndex,dropLocationIndex);
		}
	}

	void destroyReferences(){
		if (mScratch !=null){
		mScratch.recycle();
		mScratch=null;
		}
		//Log.v(TAG,"bmpPieces length = " + mBmpPieces.length);
		for(int m=0;m<mBmpPieces.length;m++){
			mBmpPieces[m].recycle();
			mBmpPieces[m]=null;
		}
		if(mGalleryList.size() >0){
			mGalleryList.clear();
		}
	}
	///Activates the tada sound when the puzzle is finished right.
	public boolean activateSound(){
		boolean playTada=false;

		///Logic to add completion sounnd for the puzzle.
		for(int j=0;j<mGalleryList.size(); j++){

			if (mGalleryList.get(j) == j){
				match++;

				if (match == mGalleryList.size()){
					match=0;
					playSound(R.raw.tada);
				    playTada=true;
				}
			} else {
				match=0;
				playTada=false;
				break;
			}
		}
		return playTada;
	}

	//plays a sound file
	public void playSound(int sFile)
	{
		//set up MediaPlayer   
		final int medFile = sFile;

		Thread thread = new Thread(new Runnable()       {

			public void run() {
				mp = MediaPlayer.create(mContext, medFile);
				mp.start();
			}
		});
		thread.start();

	}

	///Gets the bitmap from the uriPath mentioned.
	private Bitmap getBitmap(Uri galleryUriPath) {
		File cacheDir;
		// if the device has an SD card
		if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
			cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311");
		} else {
			// it does not have an SD card
			//	cacheDir=ActivityPicture.this.getCacheDir();
			cacheDir=mContext.getCacheDir();
		}
		if(!cacheDir.exists())
			cacheDir.mkdirs();

		//File f=new File(cacheDir, tag);

		try {


			BitmapFactory.Options options = new BitmapFactory.Options();
			android.content.res.AssetFileDescriptor fd = mContext.getContentResolver().openAssetFileDescriptor(galleryUriPath,"r");

			Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, options);
			fd.close();
			return bitmap;
		} catch (Exception ex) {

			ex.printStackTrace();
			return null;
		}
	}

	///Logic to create 9 pieces of the given bitmap.
	private void createBitmapPieces() {
		int k=0;
		int width=mScratch.getWidth();
		int height=mScratch.getHeight();
		mBmpPieces=new Bitmap[NUM_OF_PIECES];
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				mBmpPieces[k]=Bitmap.createBitmap(mScratch,(width*j)/3,(i*height)/3,width/3,height/3);
				//mBmpInGallery[k] = true;
				mGalleryList.add(k);
				k++;
			}
		}
		mScratch.recycle();
		mScratch=null;
		// shuffle pieces
		Collections.shuffle(mGalleryList);

	}

	///Logic to resize the bitmap to a given width.
	private void resizeBitmap() {
		int width = mScratch.getWidth();
		int height = mScratch.getHeight();
		float aspectRatio = (float) width / (float) height;
		//Display display = ((WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE)).getDefaultDisplay();
		int screenWidth = pixelsFromDp(385);
		
		//int newWidth = 800;
		//int newHeight = (int) (screenWidth / aspectRatio);  
		//mScratch.recycle();
		//mScratch=null;
		
		int newHeight= pixelsFromDp(390);
		//int screenWidth=(int) (newHeight/aspectRatio);
		mScratch=Bitmap.createScaledBitmap(mScratch, screenWidth, newHeight, false);

	}

	
	private void generateImage() {
		// Get list of images accessible by cursor

		String[] columns = new String[] {
				ImageColumns._ID,
				ImageColumns.TITLE,
				ImageColumns.DATA,
				ImageColumns.MIME_TYPE,
				ImageColumns.SIZE };
		cr =mContext.getContentResolver();
		Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				columns, null, null, null);
		Log.v(TAG,"value of cursor " + cursor);
		// Collect Picture IDs
		cursor.moveToFirst();
		ArrayList<Integer> picList = new ArrayList<Integer>();
		while (!cursor.isAfterLast()) {
			picList.add(cursor.getInt(0));
			cursor.moveToNext();
		}// end for

		// Generate random number
		int imageCount = picList.size() - 1;

		Random random = new Random();
		int randomInt = random.nextInt(imageCount);


		// Extract the image
		//int picID = picList.get(randomInt);
		int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		cursor.moveToPosition(randomInt);
		String filePath = cursor.getString(columnIndex);
		//mScratch.recycle();
		mScratch= BitmapFactory.decodeFile(filePath);
		//return decodeSampledBitmapFromResource(filePath,3264,2448);


	}// end Generate Image

}
